package com.dy.mongo.service;

import com.dy.mongo.entity.Person;
import com.dy.mongo.repository.PersonRepository;
import com.opencsv.CSVReader;
import com.opencsv.exceptions.CsvValidationException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.multipart.MultipartFile;

/**
 * 从 characters.csv 与 relations.csv 批量导入 Neo4j。
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class CsvImportService {

    private final PersonRepository personRepository;

    /**
     * 一次性导入两张 CSV。
     */
    @Transactional
    public void importCharactersAndRelations(Path charactersCsv, Path relationsCsv) throws IOException, CsvValidationException {
        Map<Long, Person> map = loadCharacters(charactersCsv);
        loadRelations(relationsCsv, map);
        // 保存所有节点（含关系列表）
        personRepository.saveAll(map.values());
        log.info("导入完成，节点数量：{}", map.size());
    }

    /**
     * 通过上传的 MultipartFile 进行导入，便于直接在接口上传。
     */
    @Transactional
    public void importCharactersAndRelations(MultipartFile charactersFile, MultipartFile relationsFile) throws IOException, CsvValidationException {
        if (charactersFile == null || relationsFile == null) {
            throw new IllegalArgumentException("上传文件不能为空");
        }
        try (Reader charReader = new InputStreamReader(charactersFile.getInputStream(), StandardCharsets.UTF_8);
             Reader relReader = new InputStreamReader(relationsFile.getInputStream(), StandardCharsets.UTF_8)) {
            Map<Long, Person> map = loadCharacters(charReader);
            loadRelations(relReader, map);
            personRepository.saveAll(map.values());
            log.info("(上传)导入完成，节点数量：{}", map.size());
        }
    }

    /**
     * 读取 characters.csv 并创建人物节点（暂不持久化）。
     */
    private Map<Long, Person> loadCharacters(Path csvPath) throws IOException, CsvValidationException {
        try (BufferedReader br = Files.newBufferedReader(csvPath, StandardCharsets.UTF_8)) {
            return loadCharacters(br);
        }
    }

    private Map<Long, Person> loadCharacters(Reader readerSource) throws IOException, CsvValidationException {
        Map<Long, Person> map = new HashMap<>();
        try (CSVReader reader = new CSVReader(readerSource)) {
            String[] header = reader.readNext(); // 跳过表头
            String[] row;
            while ((row = reader.readNext()) != null) {
                Long csvId = Long.valueOf(row[0]);
                String name = row[1];
                String alias = row.length > 2 ? row[2] : null;
                String species = row.length > 3 ? row[3] : null;

                Person p = new Person();
                p.setCsvId(csvId);
                p.setName(name);
                p.setAlias(alias);
                p.setSpecies(species);
                map.put(csvId, p);
            }
        }
        log.info("已读取人物 {} 个", map.size());
        return map;
    }

    /**
     * 根据 relations.csv 给节点加关系，不做重复校验。
     */
    private void loadRelations(Path csvPath, Map<Long, Person> people) throws IOException, CsvValidationException {
        try (BufferedReader br = Files.newBufferedReader(csvPath, StandardCharsets.UTF_8)) {
            loadRelations(br, people);
        }
    }

    private void loadRelations(Reader readerSource, Map<Long, Person> people) throws IOException, CsvValidationException {
        try (CSVReader reader = new CSVReader(readerSource)) {
            reader.readNext(); // skip header
            String[] row;
            int count = 0;
            while ((row = reader.readNext()) != null) {
                Long fromId = Long.valueOf(row[0]);
                Long toId = Long.valueOf(row[1]);
                String type = row[2];

                Person from = people.get(fromId);
                Person to = people.get(toId);
                if (from == null || to == null) {
                    log.warn("找不到节点 fromId={} 或 toId={}，跳过", fromId, toId);
                    continue;
                }
                from.addRelation(type, to);
                count++;
            }
            log.info("已读取关系 {} 条", count);
        }
    }
} 